TBB: add mbedTLS authentication related libraries
authorJuan Castillo <[email protected]>
Thu, 2 Apr 2015 14:44:20 +0000 (15:44 +0100)
committerJuan Castillo <[email protected]>
Thu, 25 Jun 2015 07:53:27 +0000 (08:53 +0100)
This patch adds the following mbedTLS based libraries:

* Cryptographic library

It is used by the crypto module to verify a digital signature
and a hash. This library relies on mbedTLS to perform the
cryptographic operations. mbedTLS sources must be obtained
separately.

Two key algorithms are currently supported:

    * RSA-2048
    * ECDSA-SECP256R1

The platform is responsible for picking up the required
algorithm by defining the 'MBEDTLS_KEY_ALG' variable in the
platform makefile. Available options are:

    * 'rsa' (for RSA-2048) (default option)
    * 'ecdsa' (for ECDSA-SECP256R1)

Hash algorithm currently supported is SHA-256.

* Image parser library

Used by the image parser module to extract the authentication
parameters stored in X509v3 certificates.

Change-Id: I597c4be3d29287f2f18b82846973afc142ee0bf0

drivers/auth/mbedtls/mbedtls_common.c [new file with mode: 0644]
drivers/auth/mbedtls/mbedtls_common.mk [new file with mode: 0644]
drivers/auth/mbedtls/mbedtls_crypto.c [new file with mode: 0644]
drivers/auth/mbedtls/mbedtls_crypto.mk [new file with mode: 0644]
drivers/auth/mbedtls/mbedtls_x509.mk [new file with mode: 0644]
drivers/auth/mbedtls/mbedtls_x509_parser.c [new file with mode: 0644]
include/drivers/auth/mbedtls/mbedtls_common.h [new file with mode: 0644]
include/drivers/auth/mbedtls/mbedtls_config.h [new file with mode: 0644]

diff --git a/drivers/auth/mbedtls/mbedtls_common.c b/drivers/auth/mbedtls/mbedtls_common.c
new file mode 100644 (file)
index 0000000..2978260
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+
+/* mbedTLS headers */
+#include <polarssl/memory_buffer_alloc.h>
+
+/*
+ * mbedTLS heap
+ */
+#if (MBEDTLS_KEY_ALG_ID == MBEDTLS_ECDSA)
+#define MBEDTLS_HEAP_SIZE              (14*1024)
+#elif (MBEDTLS_KEY_ALG_ID == MBEDTLS_RSA)
+#define MBEDTLS_HEAP_SIZE              (8*1024)
+#endif
+static unsigned char heap[MBEDTLS_HEAP_SIZE];
+
+/*
+ * mbedTLS initialization function
+ *
+ * Return: 0 = success, Otherwise = error
+ */
+void mbedtls_init(void)
+{
+       static int ready;
+       int rc;
+
+       if (!ready) {
+               /* Initialize the mbedTLS heap */
+               rc = memory_buffer_alloc_init(heap, MBEDTLS_HEAP_SIZE);
+               if (rc == 0) {
+                       ready = 1;
+               } else {
+                       assert(0);
+               }
+       }
+}
diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk
new file mode 100644 (file)
index 0000000..b71bbc9
--- /dev/null
@@ -0,0 +1,60 @@
+#
+# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+ifneq (${MBEDTLS_COMMON_MK},1)
+MBEDTLS_COMMON_MK      :=      1
+
+# MBEDTLS_DIR must be set to the mbedTLS main directory (it must contain
+# the 'include' and 'library' subdirectories).
+ifeq (${MBEDTLS_DIR},)
+  $(error Error: MBEDTLS_DIR not set)
+endif
+
+INCLUDES               +=      -I${MBEDTLS_DIR}/include                \
+                               -Iinclude/drivers/auth/mbedtls
+
+# Specify mbedTLS configuration file
+POLARSSL_CONFIG_FILE   :=      "<mbedtls_config.h>"
+$(eval $(call add_define,POLARSSL_CONFIG_FILE))
+
+MBEDTLS_COMMON_SOURCES :=      drivers/auth/mbedtls/mbedtls_common.c   \
+                               $(addprefix ${MBEDTLS_DIR}/library/,    \
+                               asn1parse.c                             \
+                               asn1write.c                             \
+                               memory_buffer_alloc.c                   \
+                               oid.c                                   \
+                               platform.c                              \
+                               )
+
+BL1_SOURCES            +=      ${MBEDTLS_COMMON_SOURCES}
+BL2_SOURCES            +=      ${MBEDTLS_COMMON_SOURCES}
+DISABLE_PEDANTIC       :=      1
+
+endif
diff --git a/drivers/auth/mbedtls/mbedtls_crypto.c b/drivers/auth/mbedtls/mbedtls_crypto.c
new file mode 100644 (file)
index 0000000..f69f930
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <crypto_mod.h>
+#include <debug.h>
+#include <mbedtls_common.h>
+#include <stddef.h>
+#include <string.h>
+
+/* mbedTLS headers */
+#include <polarssl/md_wrap.h>
+#include <polarssl/memory_buffer_alloc.h>
+#include <polarssl/oid.h>
+#include <polarssl/platform.h>
+
+#define LIB_NAME               "mbedTLS"
+
+/*
+ * AlgorithmIdentifier  ::=  SEQUENCE  {
+ *     algorithm               OBJECT IDENTIFIER,
+ *     parameters              ANY DEFINED BY algorithm OPTIONAL
+ * }
+ *
+ * SubjectPublicKeyInfo  ::=  SEQUENCE  {
+ *     algorithm            AlgorithmIdentifier,
+ *     subjectPublicKey     BIT STRING
+ * }
+ *
+ * DigestInfo ::= SEQUENCE {
+ *     digestAlgorithm AlgorithmIdentifier,
+ *     digest OCTET STRING
+ * }
+ */
+
+/*
+ * Initialize the library and export the descriptor
+ */
+static void init(void)
+{
+       /* Initialize mbedTLS */
+       mbedtls_init();
+}
+
+/*
+ * Verify a signature.
+ *
+ * Parameters are passed using the DER encoding format following the ASN.1
+ * structures detailed above.
+ */
+static int verify_signature(void *data_ptr, unsigned int data_len,
+                           void *sig_ptr, unsigned int sig_len,
+                           void *sig_alg, unsigned int sig_alg_len,
+                           void *pk_ptr, unsigned int pk_len)
+{
+       asn1_buf sig_oid, sig_params;
+       asn1_buf signature;
+       md_type_t md_alg;
+       pk_type_t pk_alg;
+       pk_context pk;
+       int rc;
+       void *sig_opts = NULL;
+       const md_info_t *md_info;
+       unsigned char *p, *end;
+       unsigned char hash[POLARSSL_MD_MAX_SIZE];
+
+       /* Get pointers to signature OID and parameters */
+       p = (unsigned char *)sig_alg;
+       end = (unsigned char *)(p + sig_alg_len);
+       rc = asn1_get_alg(&p, end, &sig_oid, &sig_params);
+       if (rc != 0) {
+               return CRYPTO_ERR_SIGNATURE;
+       }
+
+       /* Get the actual signature algorithm (MD + PK) */
+       rc = oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg);
+       if (rc != 0) {
+               return CRYPTO_ERR_SIGNATURE;
+       }
+
+       /* Parse the public key */
+       pk_init(&pk);
+       p = (unsigned char *)pk_ptr;
+       end = (unsigned char *)(p + pk_len);
+       rc = pk_parse_subpubkey(&p, end, &pk);
+       if (rc != 0) {
+               return CRYPTO_ERR_SIGNATURE;
+       }
+
+       /* Get the signature (bitstring) */
+       p = (unsigned char *)sig_ptr;
+       end = (unsigned char *)(p + sig_len);
+       signature.tag = *p;
+       rc = asn1_get_bitstring_null(&p, end, &signature.len);
+       if (rc != 0) {
+               rc = CRYPTO_ERR_SIGNATURE;
+               goto end;
+       }
+       signature.p = p;
+
+       /* Calculate the hash of the data */
+       md_info = md_info_from_type(md_alg);
+       if (md_info == NULL) {
+               rc = CRYPTO_ERR_SIGNATURE;
+               goto end;
+       }
+       p = (unsigned char *)data_ptr;
+       rc = md(md_info, p, data_len, hash);
+       if (rc != 0) {
+               rc = CRYPTO_ERR_SIGNATURE;
+               goto end;
+       }
+
+       /* Verify the signature */
+       rc = pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash,
+                       md_info->size, signature.p, signature.len);
+       if (rc != 0) {
+               rc = CRYPTO_ERR_SIGNATURE;
+               goto end;
+       }
+
+       /* Signature verification success */
+       rc = CRYPTO_SUCCESS;
+
+end:
+       pk_free(&pk);
+       return rc;
+}
+
+/*
+ * Match a hash
+ *
+ * Digest info is passed in DER format following the ASN.1 structure detailed
+ * above.
+ */
+static int verify_hash(void *data_ptr, unsigned int data_len,
+                      void *digest_info_ptr, unsigned int digest_info_len)
+{
+       asn1_buf hash_oid, params;
+       md_type_t md_alg;
+       const md_info_t *md_info;
+       unsigned char *p, *end, *hash;
+       unsigned char data_hash[POLARSSL_MD_MAX_SIZE];
+       size_t len;
+       int rc;
+
+       /* Digest info should be an ASN1_SEQUENCE */
+       p = (unsigned char *)digest_info_ptr;
+       end = (unsigned char *)(digest_info_ptr + digest_info_len);
+       rc = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+       if (rc != 0) {
+               return CRYPTO_ERR_HASH;
+       }
+
+       /* Get the hash algorithm */
+       rc = asn1_get_alg(&p, end, &hash_oid, &params);
+       if (rc != 0) {
+               return CRYPTO_ERR_HASH;
+       }
+
+       rc = oid_get_md_alg(&hash_oid, &md_alg);
+       if (rc != 0) {
+               return CRYPTO_ERR_HASH;
+       }
+
+       md_info = md_info_from_type(md_alg);
+       if (md_info == NULL) {
+               return CRYPTO_ERR_HASH;
+       }
+
+       /* Hash should be octet string type */
+       rc = asn1_get_tag(&p, end, &len, ASN1_OCTET_STRING);
+       if (rc != 0) {
+               return CRYPTO_ERR_HASH;
+       }
+
+       /* Length of hash must match the algorithm's size */
+       if (len != md_info->size) {
+               return CRYPTO_ERR_HASH;
+       }
+       hash = p;
+
+       /* Calculate the hash of the data */
+       p = (unsigned char *)data_ptr;
+       rc = md(md_info, p, data_len, data_hash);
+       if (rc != 0) {
+               return CRYPTO_ERR_HASH;
+       }
+
+       /* Compare values */
+       rc = memcmp(data_hash, hash, md_info->size);
+       if (rc != 0) {
+               return CRYPTO_ERR_HASH;
+       }
+
+       return CRYPTO_SUCCESS;
+}
+
+/*
+ * Register crypto library descriptor
+ */
+REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);
diff --git a/drivers/auth/mbedtls/mbedtls_crypto.mk b/drivers/auth/mbedtls/mbedtls_crypto.mk
new file mode 100644 (file)
index 0000000..67d2eb4
--- /dev/null
@@ -0,0 +1,72 @@
+#
+# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+include drivers/auth/mbedtls/mbedtls_common.mk
+
+# The platform may define the variable 'MBEDTLS_KEY_ALG' to select the key
+# algorithm to use. Default algorithm is ECDSA.
+ifeq (${MBEDTLS_KEY_ALG},)
+    MBEDTLS_KEY_ALG            :=      rsa
+endif
+
+MBEDTLS_CRYPTO_SOURCES         :=      drivers/auth/mbedtls/mbedtls_crypto.c   \
+                                       $(addprefix ${MBEDTLS_DIR}/library/,    \
+                                       bignum.c                                \
+                                       md.c                                    \
+                                       md_wrap.c                               \
+                                       pk.c                                    \
+                                       pk_wrap.c                               \
+                                       pkparse.c                               \
+                                       pkwrite.c                               \
+                                       sha256.c                                \
+                                       )
+
+# Key algorithm specific files
+ifeq (${MBEDTLS_KEY_ALG},ecdsa)
+    MBEDTLS_CRYPTO_SOURCES     +=      $(addprefix ${MBEDTLS_DIR}/library/,    \
+                                       ecdsa.c                                 \
+                                       ecp_curves.c                            \
+                                       ecp.c                                   \
+                                       )
+    MBEDTLS_KEY_ALG_ID         :=      MBEDTLS_ECDSA
+else ifeq (${MBEDTLS_KEY_ALG},rsa)
+    MBEDTLS_CRYPTO_SOURCES     +=      $(addprefix ${MBEDTLS_DIR}/library/,    \
+                                       rsa.c                                   \
+                                       )
+    MBEDTLS_KEY_ALG_ID         :=      MBEDTLS_RSA
+else
+    $(error "MBEDTLS_KEY_ALG=${MBEDTLS_KEY_ALG} not supported on mbedTLS")
+endif
+
+# mbedTLS libraries rely on this define to build correctly
+$(eval $(call add_define,MBEDTLS_KEY_ALG_ID))
+
+BL1_SOURCES                    +=      ${MBEDTLS_CRYPTO_SOURCES}
+BL2_SOURCES                    +=      ${MBEDTLS_CRYPTO_SOURCES}
diff --git a/drivers/auth/mbedtls/mbedtls_x509.mk b/drivers/auth/mbedtls/mbedtls_x509.mk
new file mode 100644 (file)
index 0000000..3f9420d
--- /dev/null
@@ -0,0 +1,40 @@
+#
+# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# Neither the name of ARM nor the names of its contributors may be used
+# to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+include drivers/auth/mbedtls/mbedtls_common.mk
+
+MBEDTLS_X509_SOURCES   :=      drivers/auth/mbedtls/mbedtls_x509_parser.c      \
+                               $(addprefix ${MBEDTLS_DIR}/library/,            \
+                               x509.c                                          \
+                               x509_crt.c                                      \
+                               )
+
+BL1_SOURCES            +=      ${MBEDTLS_X509_SOURCES}
+BL2_SOURCES            +=      ${MBEDTLS_X509_SOURCES}
diff --git a/drivers/auth/mbedtls/mbedtls_x509_parser.c b/drivers/auth/mbedtls/mbedtls_x509_parser.c
new file mode 100644 (file)
index 0000000..a8605ce
--- /dev/null
@@ -0,0 +1,438 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * X509 parser based on PolarSSL
+ *
+ * This module implements functions to check the integrity of a X509v3
+ * certificate ASN.1 structure and extract authentication parameters from the
+ * extensions field, such as an image hash or a public key.
+ */
+
+#include <assert.h>
+#include <img_parser_mod.h>
+#include <mbedtls_common.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+/* mbedTLS headers */
+#include <polarssl/asn1.h>
+#include <polarssl/oid.h>
+#include <polarssl/platform.h>
+
+/* Maximum OID string length ("a.b.c.d.e.f ...") */
+#define MAX_OID_STR_LEN                        64
+
+#define LIB_NAME       "mbedTLS X509v3"
+
+/* Temporary variables to speed up the authentication parameters search. These
+ * variables are assigned once during the integrity check and used any time an
+ * authentication parameter is requested, so we do not have to parse the image
+ * again */
+static asn1_buf tbs;
+static asn1_buf v3_ext;
+static asn1_buf pk;
+static asn1_buf sig_alg;
+static asn1_buf signature;
+
+/*
+ * Get X509v3 extension
+ *
+ * Global variable 'v3_ext' must point to the extensions region
+ * in the certificate. No need to check for errors since the image has passed
+ * the integrity check.
+ */
+static int get_ext(const char *oid, void **ext, unsigned int *ext_len)
+{
+       int oid_len;
+       size_t len;
+       unsigned char *end_ext_data, *end_ext_octet;
+       unsigned char *p;
+       const unsigned char *end;
+       char oid_str[MAX_OID_STR_LEN];
+       asn1_buf extn_oid;
+       int is_critical;
+
+       assert(oid != NULL);
+
+       p = v3_ext.p;
+       end = v3_ext.p + v3_ext.len;
+
+       asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+
+       while (p < end) {
+               memset(&extn_oid, 0x0, sizeof(extn_oid));
+               is_critical = 0; /* DEFAULT FALSE */
+
+               asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+               end_ext_data = p + len;
+
+               /* Get extension ID */
+               extn_oid.tag = *p;
+               asn1_get_tag(&p, end, &extn_oid.len, ASN1_OID);
+               extn_oid.p = p;
+               p += extn_oid.len;
+
+               /* Get optional critical */
+               asn1_get_bool(&p, end_ext_data, &is_critical);
+
+               /* Extension data */
+               asn1_get_tag(&p, end_ext_data, &len, ASN1_OCTET_STRING);
+               end_ext_octet = p + len;
+
+               /* Detect requested extension */
+               oid_len = oid_get_numeric_string(oid_str,
+                               MAX_OID_STR_LEN, &extn_oid);
+               if (oid_len == POLARSSL_ERR_OID_BUF_TOO_SMALL) {
+                       return IMG_PARSER_ERR;
+               }
+               if ((oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) {
+                       *ext = (void *)p;
+                       *ext_len = (unsigned int)len;
+                       return IMG_PARSER_OK;
+               }
+
+               /* Next */
+               p = end_ext_octet;
+       }
+
+       return IMG_PARSER_ERR_NOT_FOUND;
+}
+
+
+/*
+ * Check the integrity of the certificate ASN.1 structure.
+ * Extract the relevant data that will be used later during authentication.
+ */
+static int cert_parse(void *img, unsigned int img_len)
+{
+       int ret, is_critical;
+       size_t len;
+       unsigned char *p, *end, *crt_end;
+       asn1_buf sig_alg1, sig_alg2;
+
+       p = (unsigned char *)img;
+       len = img_len;
+       end = p + len;
+
+       /*
+        * Certificate  ::=  SEQUENCE  {
+        *      tbsCertificate       TBSCertificate,
+        *      signatureAlgorithm   AlgorithmIdentifier,
+        *      signatureValue       BIT STRING  }
+        */
+       ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+       if (ret != 0) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+
+       if (len > (size_t)(end - p)) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       crt_end = p + len;
+
+       /*
+        * TBSCertificate  ::=  SEQUENCE  {
+        */
+       tbs.p = p;
+       ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+       if (ret != 0) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       end = p + len;
+       tbs.len = end - tbs.p;
+
+       /*
+        * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
+        */
+       ret = asn1_get_tag(&p, end, &len,
+                       ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0);
+       if (ret != 0) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       p += len;
+
+       /*
+        * CertificateSerialNumber  ::=  INTEGER
+        */
+       ret = asn1_get_tag(&p, end, &len, ASN1_INTEGER);
+       if (ret != 0) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       p += len;
+
+       /*
+        * signature            AlgorithmIdentifier
+        */
+       sig_alg1.p = p;
+       ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+       if (ret != 0) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       if ((end - p) < 1) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       sig_alg1.len = (p + len) - sig_alg1.p;
+       p += len;
+
+       /*
+        * issuer               Name
+        */
+       ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+       if (ret != 0) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       p += len;
+
+       /*
+        * Validity ::= SEQUENCE {
+        *      notBefore      Time,
+        *      notAfter       Time }
+        *
+        */
+       ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+       if (ret != 0) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       p += len;
+
+       /*
+        * subject              Name
+        */
+       ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+       if (ret != 0) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       p += len;
+
+       /*
+        * SubjectPublicKeyInfo
+        */
+       pk.p = p;
+       ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+       if (ret != 0) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       pk.len = (p + len) - pk.p;
+       p += len;
+
+       /*
+        * issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
+        */
+       ret = asn1_get_tag(&p, end, &len,
+                       ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1);
+       if (ret != 0) {
+               if (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG) {
+                       return IMG_PARSER_ERR_FORMAT;
+               }
+       } else {
+               p += len;
+       }
+
+       /*
+        * subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
+        */
+       ret = asn1_get_tag(&p, end, &len,
+                       ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 2);
+       if (ret != 0) {
+               if (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG) {
+                       return IMG_PARSER_ERR_FORMAT;
+               }
+       } else {
+               p += len;
+       }
+
+       /*
+        * extensions      [3]  EXPLICIT Extensions OPTIONAL
+        */
+       ret = asn1_get_tag(&p, end, &len,
+                       ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3);
+       if (ret != 0) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+
+       /*
+        * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
+        */
+       v3_ext.p = p;
+       ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+       if (ret != 0) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       v3_ext.len = (p + len) - v3_ext.p;
+
+       /*
+        * Check extensions integrity
+        */
+       while (p < end) {
+               ret = asn1_get_tag(&p, end, &len,
+                               ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+               if (ret != 0) {
+                       return IMG_PARSER_ERR_FORMAT;
+               }
+
+               /* Get extension ID */
+               ret = asn1_get_tag(&p, end, &len, ASN1_OID);
+               if (ret != 0) {
+                       return IMG_PARSER_ERR_FORMAT;
+               }
+               p += len;
+
+               /* Get optional critical */
+               ret = asn1_get_bool(&p, end, &is_critical);
+               if ((ret != 0) && (ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG)) {
+                       return IMG_PARSER_ERR_FORMAT;
+               }
+
+               /* Data should be octet string type */
+               ret = asn1_get_tag(&p, end, &len, ASN1_OCTET_STRING);
+               if (ret != 0) {
+                       return IMG_PARSER_ERR_FORMAT;
+               }
+               p += len;
+       }
+
+       if (p != end) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+
+       end = crt_end;
+
+       /*
+        *  }
+        *  -- end of TBSCertificate
+        *
+        *  signatureAlgorithm   AlgorithmIdentifier
+        */
+       sig_alg2.p = p;
+       ret = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
+       if (ret != 0) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       if ((end - p) < 1) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       sig_alg2.len = (p + len) - sig_alg2.p;
+       p += len;
+
+       /* Compare both signature algorithms */
+       if (sig_alg1.len != sig_alg2.len) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       if (0 != memcmp(sig_alg1.p, sig_alg2.p, sig_alg1.len)) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       memcpy(&sig_alg, &sig_alg1, sizeof(sig_alg));
+
+       /*
+        * signatureValue       BIT STRING
+        */
+       signature.p = p;
+       ret = asn1_get_tag(&p, end, &len, ASN1_BIT_STRING);
+       if (ret != 0) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+       signature.len = (p + len) - signature.p;
+       p += len;
+
+       /* Check certificate length */
+       if (p != end) {
+               return IMG_PARSER_ERR_FORMAT;
+       }
+
+       return IMG_PARSER_OK;
+}
+
+
+/* Exported functions */
+
+static void init(void)
+{
+       mbedtls_init();
+}
+
+static int check_integrity(void *img, unsigned int img_len)
+{
+       return cert_parse(img, img_len);
+}
+
+/*
+ * Extract an authentication parameter from an X509v3 certificate
+ */
+static int get_auth_param(const auth_param_type_desc_t *type_desc,
+               void *img, unsigned int img_len,
+               void **param, unsigned int *param_len)
+{
+       int rc = IMG_PARSER_OK;
+
+       /* We do not use img because the check_integrity function has already
+        * extracted the relevant data (v3_ext, pk, sig_alg, etc) */
+
+       switch (type_desc->type) {
+       case AUTH_PARAM_RAW_DATA:
+               /* Data to be signed */
+               *param = (void *)tbs.p;
+               *param_len = (unsigned int)tbs.len;
+               break;
+       case AUTH_PARAM_HASH:
+               /* All these parameters are included as X509v3 extensions */
+               rc = get_ext(type_desc->cookie, param, param_len);
+               break;
+       case AUTH_PARAM_PUB_KEY:
+               if (type_desc->cookie != 0) {
+                       /* Get public key from extension */
+                       rc = get_ext(type_desc->cookie, param, param_len);
+               } else {
+                       /* Get the subject public key */
+                       *param = (void *)pk.p;
+                       *param_len = (unsigned int)pk.len;
+               }
+               break;
+       case AUTH_PARAM_SIG_ALG:
+               /* Get the certificate signature algorithm */
+               *param = (void *)sig_alg.p;
+               *param_len = (unsigned int)sig_alg.len;
+               break;
+       case AUTH_PARAM_SIG:
+               /* Get the certificate signature */
+               *param = (void *)signature.p;
+               *param_len = (unsigned int)signature.len;
+               break;
+       default:
+               rc = IMG_PARSER_ERR_NOT_FOUND;
+               break;
+       }
+
+       return rc;
+}
+
+REGISTER_IMG_PARSER_LIB(IMG_CERT, LIB_NAME, init, \
+                      check_integrity, get_auth_param);
diff --git a/include/drivers/auth/mbedtls/mbedtls_common.h b/include/drivers/auth/mbedtls/mbedtls_common.h
new file mode 100644 (file)
index 0000000..eb22e8a
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MBEDTLS_COMMON_H__
+#define __MBEDTLS_COMMON_H__
+
+void mbedtls_init(void);
+
+#endif /* __MBEDTLS_COMMON_H__ */
diff --git a/include/drivers/auth/mbedtls/mbedtls_config.h b/include/drivers/auth/mbedtls/mbedtls_config.h
new file mode 100644 (file)
index 0000000..8a000f0
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __MBEDTLS_CONFIG_H__
+#define __MBEDTLS_CONFIG_H__
+
+/*
+ * Key algorithms currently supported on mbedTLS libraries
+ */
+#define MBEDTLS_RSA                    1
+#define MBEDTLS_ECDSA                  2
+
+/*
+ * Configuration file to build PolarSSL with the required features for
+ * Trusted Boot
+ */
+
+#define POLARSSL_PLATFORM_MEMORY
+#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS
+
+#define POLARSSL_PKCS1_V15
+#define POLARSSL_PKCS1_V21
+
+#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+#define POLARSSL_X509_CHECK_KEY_USAGE
+#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE
+
+#define POLARSSL_ASN1_PARSE_C
+#define POLARSSL_ASN1_WRITE_C
+
+#define POLARSSL_BASE64_C
+#define POLARSSL_BIGNUM_C
+
+#define POLARSSL_ERROR_C
+#define POLARSSL_MD_C
+
+#define POLARSSL_MEMORY_BUFFER_ALLOC_C
+#define POLARSSL_OID_C
+
+#define POLARSSL_PK_C
+#define POLARSSL_PK_PARSE_C
+#define POLARSSL_PK_WRITE_C
+
+#define POLARSSL_PLATFORM_C
+
+#if (MBEDTLS_KEY_ALG_ID == MBEDTLS_ECDSA)
+#define POLARSSL_ECDSA_C
+#define POLARSSL_ECP_C
+#define POLARSSL_ECP_DP_SECP256R1_ENABLED
+#elif (MBEDTLS_KEY_ALG_ID == MBEDTLS_RSA)
+#define POLARSSL_RSA_C
+#endif
+
+#define POLARSSL_SHA256_C
+
+#define POLARSSL_VERSION_C
+
+#define POLARSSL_X509_USE_C
+#define POLARSSL_X509_CRT_PARSE_C
+
+/* MPI / BIGNUM options */
+#define POLARSSL_MPI_WINDOW_SIZE              2
+#define POLARSSL_MPI_MAX_SIZE               256
+
+/* Memory buffer allocator options */
+#define POLARSSL_MEMORY_ALIGN_MULTIPLE        8
+
+#include "polarssl/check_config.h"
+
+/* System headers required to build mbedTLS with the current configuration */
+#include <stdlib.h>
+
+#endif /* __MBEDTLS_CONFIG_H__ */